#ifndef Object_h
#define Object_h
#include "Abstract.h"

#define GRAVITATIONAL_CONSTANT 6.67428e-11

class Object : public Abstract
{
public:
	Object(type p_type, color p_color,
		double p_mass, double p_radius,
		Vector2 p_pos, Vector2 p_velocity)
	: Abstract(p_type, p_pos, p_color)
	{
		m_mass = p_mass;
		m_radius = p_radius;
		m_velocity = p_velocity;

		m_explode_charges = 5; // missiles override this in their constructor (to 1)

		m_health = GC_STAR_HEALTH; //missiles & planets override this
		/*switch(p_type)
		{
			case(STAR):
				m_health = GC_STAR_HEALTH;
				break;
			case(PLANET):
				m_health = GC_PLANET_HEALTH;
				break;
			case(MISSILE):
				m_health = GC_MISSILE_HEALTH;
				break;
			default:
				m_health = 0;
				break;
		}*/
	}

	double getMass() const
	{
		return m_mass;
	}
	double getRadius() const
	{
		return m_radius;
	}
	Vector2 getVelocity() const
	{
		return m_velocity;
	}
	unsigned int getHealth() const
	{
		return m_health;
	}

	bool doneExploding() const
	{
		return (bool)(m_explode_charges == 0);
	}
	virtual bool useExplosionCharge()
	{
		m_explode_charges--;
		
		return true;
	}
	bool collide(Object* p_kaka) const
	{
		// check missile age to avoid them blowing up instantly
		if ( (getType() == MISSILE && getAge() < GC_MISSILE_BLOW_UP_AGE) || (p_kaka->getType() == MISSILE && p_kaka->getAge() < GC_MISSILE_BLOW_UP_AGE) )
			return false;
		return collide(p_kaka->getRadius(), p_kaka->getPosition() );	
	}
	bool collide(double p_radius, Vector2 p_position) const
	{
		Vector2 diff = m_position-p_position;

		return (bool)(diff.getLength() < (m_radius+p_radius)*GC_STARTING_SCALE);		
	}
	void damage(unsigned int p_dmg)
	{
		std::cout << "current: " << m_health << "; damage: " << p_dmg << std::endl;
		if (p_dmg > m_health)
			kill();
		else 
			m_health -= p_dmg;
	}
	void kill()
	{
		m_health = 0;
	}
	virtual void updatePosition(double p_dt)
	{
		Vector2 a = m_resulting_force / m_mass;
		m_position = m_position + m_velocity*p_dt + a*p_dt*p_dt*0.5;
		m_resulting_force = Vector2(0,0);
		m_velocity = m_velocity + a*p_dt;
	}
	void calculateForce(Object* p_other)
	{
		Vector2 r = p_other->getPosition() - m_position;
		double u = 0;
		if(r.getLength())
		{
			u = GRAVITATIONAL_CONSTANT*(p_other->getMass()*m_mass)/(r.getLength()*r.getLength()*r.getLength());
		}
		Vector2 F = r*u;
		m_resulting_force = m_resulting_force+F;
		p_other->setResultingForce(p_other->getResultingForce() - F);	
	}
	void setResultingForce(Vector2 p_resulting_force)
	{
		m_resulting_force = p_resulting_force;
	}
	Vector2 getResultingForce() const
	{
		return m_resulting_force;
	}
protected:
	double m_radius;
	double m_mass;
	Vector2 m_velocity;
	Vector2 m_resulting_force;

	unsigned int m_explode_charges;
	unsigned int m_health;
};


#endif //Object_h


